#include "draw.h"

#include "graphics.h"

////////////////////////////////////////////////////////////////////////////////

struct DrawState
{
  Material std_material;
};

static DrawState state;

////////////////////////////////////////////////////////////////////////////////

void Draw_init()
{
  Graphics_initMaterial(&state.std_material);
}

void Draw_pushOffset(const Point& offset)
{
  Matrix3x2 matrix;
  
  Matrix3x2_genTranslation(&matrix, offset.x, offset.y);
  
  Graphics_pushMatrix();
  Graphics_multMatrix(matrix);
}

void Draw_popOffset()
{
  Graphics_popMatrix();
}

void Draw_fillRect(const Rect& rect, Colour colour)
{
  VertexP2C vertex[4];
  unsigned short index[6];
  
  vertex[0].pos.x = rect.x;
  vertex[0].pos.y = rect.y;
  vertex[0].colour = colour;
  vertex[1].pos.x = rect.x + rect.w;
  vertex[1].pos.y = rect.y;
  vertex[1].colour = colour;
  vertex[2].pos.x = rect.x + rect.w;
  vertex[2].pos.y = rect.y + rect.h;
  vertex[2].colour = colour;
  vertex[3].pos.x = rect.x;
  vertex[3].pos.y = rect.y + rect.h;
  vertex[3].colour = colour;
  
  index[0] = 0;
  index[1] = 1;
  index[2] = 2;
  index[3] = 2;
  index[4] = 3;
  index[5] = 0;
  
  Graphics_draw(VertexP2C::type, PRIMITIVE_TRIANGLES, state.std_material,
    4, vertex, 6, index);
}

void Draw_drawRect(const Rect& rect, int width, Colour colour)
{
  VertexP2C vertex[8];
  unsigned short index[24];
  
  vertex[0].pos.x = rect.x;
  vertex[0].pos.y = rect.y;
  vertex[0].colour = colour;
  vertex[1].pos.x = rect.x + rect.w;
  vertex[1].pos.y = rect.y;
  vertex[1].colour = colour;
  vertex[2].pos.x = rect.x + rect.w;
  vertex[2].pos.y = rect.y + rect.h;
  vertex[2].colour = colour;
  vertex[3].pos.x = rect.x;
  vertex[3].pos.y = rect.y + rect.h;
  vertex[3].colour = colour;
  vertex[4].pos.x = rect.x + width;
  vertex[4].pos.y = rect.y + width;
  vertex[4].colour = colour;
  vertex[5].pos.x = rect.x + rect.w - width;
  vertex[5].pos.y = rect.y + width;
  vertex[5].colour = colour;
  vertex[6].pos.x = rect.x + rect.w - width;
  vertex[6].pos.y = rect.y + rect.h - width;
  vertex[6].colour = colour;
  vertex[7].pos.x = rect.x + width;
  vertex[7].pos.y = rect.y + rect.h - width;
  vertex[7].colour = colour;
  
  index[ 0] = 0;
  index[ 1] = 1;
  index[ 2] = 5;
  index[ 3] = 5;
  index[ 4] = 4;
  index[ 5] = 0;
  index[ 6] = 1;
  index[ 7] = 2;
  index[ 8] = 6;
  index[ 9] = 6;
  index[10] = 5;
  index[11] = 1;
  index[12] = 2;
  index[13] = 3;
  index[14] = 7;
  index[15] = 7;
  index[16] = 6;
  index[17] = 2;
  index[18] = 3;
  index[19] = 0;
  index[20] = 4;
  index[21] = 4;
  index[22] = 7;
  index[23] = 3;
  
  Graphics_draw(VertexP2C::type, PRIMITIVE_TRIANGLES, state.std_material,
    8, vertex, 24, index);
}

void Draw_drawRect3D(const Rect& rect, int width, Colour colour_tl,
  Colour colour_c, Colour colour_br)
{
  VertexP2C vertex[16];
  unsigned short index[30];
  
  vertex[0].pos.x = rect.x;
  vertex[0].pos.y = rect.y;
  vertex[0].colour = colour_tl;
  vertex[1].pos.x = rect.x + rect.w;
  vertex[1].pos.y = rect.y;
  vertex[1].colour = colour_tl;
  vertex[2].pos.x = rect.x + rect.w - width;
  vertex[2].pos.y = rect.y + width;
  vertex[2].colour = colour_tl;
  vertex[3].pos.x = rect.x + width;
  vertex[3].pos.y = rect.y + width;
  vertex[3].colour = colour_tl;
  vertex[4].pos.x = rect.x + width;
  vertex[4].pos.y = rect.y + rect.h - width;
  vertex[4].colour = colour_tl;
  vertex[5].pos.x = rect.x;
  vertex[5].pos.y = rect.y + rect.h;
  vertex[5].colour = colour_tl;
  
  vertex[ 6].pos.x = rect.x + rect.w;
  vertex[ 6].pos.y = rect.y;
  vertex[ 6].colour = colour_br;
  vertex[ 7].pos.x = rect.x + rect.w;
  vertex[ 7].pos.y = rect.y + rect.h;
  vertex[ 7].colour = colour_br;
  vertex[ 8].pos.x = rect.x;
  vertex[ 8].pos.y = rect.y + rect.h;
  vertex[ 8].colour = colour_br;
  vertex[ 9].pos.x = rect.x + width;
  vertex[ 9].pos.y = rect.y + rect.h - width;
  vertex[ 9].colour = colour_br;
  vertex[10].pos.x = rect.x + rect.w - width;
  vertex[10].pos.y = rect.y + rect.h - width;
  vertex[10].colour = colour_br;
  vertex[11].pos.x = rect.x + rect.w - width;
  vertex[11].pos.y = rect.y + width;
  vertex[11].colour = colour_br;
  
  vertex[12].pos.x = rect.x + width;
  vertex[12].pos.y = rect.y + width;
  vertex[12].colour = colour_c;
  vertex[13].pos.x = rect.x + rect.w - width;
  vertex[13].pos.y = rect.y + width;
  vertex[13].colour = colour_c;
  vertex[14].pos.x = rect.x + rect.w - width;
  vertex[14].pos.y = rect.y + rect.h - width;
  vertex[14].colour = colour_c;
  vertex[15].pos.x = rect.x + width;
  vertex[15].pos.y = rect.y + rect.h - width;
  vertex[15].colour = colour_c;
  
  index[ 0] = 0;
  index[ 1] = 1;
  index[ 2] = 2;
  index[ 3] = 2;
  index[ 4] = 3;
  index[ 5] = 0;
  index[ 6] = 3;
  index[ 7] = 4;
  index[ 8] = 5;
  index[ 9] = 5;
  index[10] = 0;
  index[11] = 3;
  
  index[12] =  6;
  index[13] =  7;
  index[14] = 10;
  index[15] = 10;
  index[16] = 11;
  index[17] =  6;
  index[18] =  7;
  index[19] =  8;
  index[20] =  9;
  index[21] =  9;
  index[22] = 10;
  index[23] =  7;
  
  index[24] = 12;
  index[25] = 13;
  index[26] = 14;
  index[27] = 14;
  index[28] = 15;
  index[29] = 12;
  
  Graphics_draw(VertexP2C::type, PRIMITIVE_TRIANGLES, state.std_material,
    16, vertex, 30, index);
}

void Draw_drawTexRect(const Material& material, const Rect& rect)
{
  VertexP2T2 vertex[4];
  unsigned short index[6];
  
  vertex[0].pos.x = rect.x;
  vertex[0].pos.y = rect.y;
  vertex[0].tex.x = 0.0f;
  vertex[0].tex.y = 0.0f;
  vertex[1].pos.x = rect.x + rect.w;
  vertex[1].pos.y = rect.y;
  vertex[1].tex.x = 1.0f;
  vertex[1].tex.y = 0.0f;
  vertex[2].pos.x = rect.x + rect.w;
  vertex[2].pos.y = rect.y + rect.h;
  vertex[2].tex.x = 1.0f;
  vertex[2].tex.y = 1.0f;
  vertex[3].pos.x = rect.x;
  vertex[3].pos.y = rect.y + rect.h;
  vertex[3].tex.x = 0.0f;
  vertex[3].tex.y = 1.0f;
  
  index[0] = 0;
  index[1] = 1;
  index[2] = 2;
  index[3] = 2;
  index[4] = 3;
  index[5] = 0;
  
  Graphics_draw(VertexP2T2::type, PRIMITIVE_TRIANGLES, material,
    4, vertex, 6, index);
}

void Draw_drawSubTexRect(const Material& material,
  const Dimension& tex_dim, const Rect& sub_rect, const Point& pos)
{
  const float rec_w = 1.0f / tex_dim.w;
  const float rec_h = 1.0f / tex_dim.h;
  VertexP2T2 vertex[4];
  unsigned short index[6];
  
  vertex[0].pos.x = pos.x;
  vertex[0].pos.y = pos.y;
  vertex[0].tex.x = rec_w * sub_rect.x;
  vertex[0].tex.y = rec_h * sub_rect.y;
  vertex[1].pos.x = pos.x + sub_rect.w;
  vertex[1].pos.y = pos.y;
  vertex[1].tex.x = rec_w * (sub_rect.x + sub_rect.w);
  vertex[1].tex.y = rec_h * sub_rect.y;
  vertex[2].pos.x = pos.x + sub_rect.w;
  vertex[2].pos.y = pos.y + sub_rect.h;
  vertex[2].tex.x = rec_w * (sub_rect.x + sub_rect.w);
  vertex[2].tex.y = rec_h * (sub_rect.y + sub_rect.h);
  vertex[3].pos.x = pos.x;
  vertex[3].pos.y = pos.y + sub_rect.h;
  vertex[3].tex.x = rec_w * sub_rect.x;
  vertex[3].tex.y = rec_h * (sub_rect.y + sub_rect.h);
  
  index[0] = 0;
  index[1] = 1;
  index[2] = 2;
  index[3] = 2;
  index[4] = 3;
  index[5] = 0;
  
  Graphics_draw(VertexP2T2::type, PRIMITIVE_TRIANGLES, material,
    4, vertex, 6, index);
}
